package com.tungse.juc.forkjoin;

import cn.hutool.core.date.StopWatch;

import java.lang.invoke.VarHandle;
import java.util.concurrent.*;
import java.util.stream.LongStream;

public class ForkJoin_Demo {
    public static void main(String[] args) throws Exception {
//        ForkJoinPool pool = new ForkJoinPool(); //创建线程池

        Long start = 0L;
        Long end = 1_000_000_0000L;
        Long sum = 0L;
        //创建计时器
        StopWatch stopWatch = new StopWatch();

        //开始计时
        stopWatch.start("normal plus");
        sum = normalPlus(start, end);
        System.out.println("normal plus==========" + sum);
        stopWatch.stop();        //结束计时

        //开始计时
        stopWatch.start("forkjoin plus");
        sum = forkJoinPlus(start, end);
        System.out.println("forkjoin plus==========" + sum);
        stopWatch.stop();        //结束计时


        //开始计时
        stopWatch.start("stream plus");
        sum = streamPlus(start, end);
        System.out.println("stream plus==========" + sum);
        stopWatch.stop();        //结束计时


        //打印计时结果
        System.out.println(stopWatch.prettyPrint(TimeUnit.MILLISECONDS));
    }

    public static Long streamPlus(long start, long end) {
        return LongStream.rangeClosed(start, end).parallel().sum();
    }

    //forkjoin求和
    public static Long forkJoinPlus(long start, long end) throws Exception {
        ForkJoinPool pool = new ForkJoinPool();
        ForkJoinTask<Long> forkJoinTest = new ForkJoinTest(start, end);
//        Long invoke = pool.invoke(forkJoinTest);
        ForkJoinTask<Long> submit = pool.submit(forkJoinTest);

        return submit.get();
    }

    //普通for循环求和
    public static Long normalPlus(long start, long end) {
        long sum = 0L;
        for (long i = start; i < end; i++) {
            sum += i;
        }
        return sum;
    }
}


class ForkJoinTest extends RecursiveTask<Long> {
    // 阈值
    private static final int THRESHOLD = 1000;
    //private int[] array;
    private long start;
    private long end;

    public ForkJoinTest(long start, long end) {
        //this.array = array;
        this.start = start;
        this.end = end;
    }

    @Override
    protected Long compute() {
        if (end - start <= THRESHOLD) {
            // 小任务，直接计算
            long sum = 0;
            for (long i = start; i < end; i++) {
                sum += i;
            }
            return sum;
        } else {
//            // 大任务，分解
//            long middle = (start + end) / 2;
//            ForkJoinTest leftTask = new ForkJoinTest(start, middle);
//            ForkJoinTest rightTask = new ForkJoinTest(middle, end);
//
//            // 执行子任务
//            leftTask.fork();
//            rightTask.fork();
//
//            // 合并结果
//            long leftResult = leftTask.join();
//            long rightResult = rightTask.join();
//            return leftResult + rightResult;
            ForkJoinTask<Long> leftTask = new ForkJoinTest(start, (start + end) / 2).fork();
            ForkJoinTask<Long> rightTask = new ForkJoinTest((start + end) / 2 , end).fork();
            Long leftSum = leftTask.join();
            Long rightSum = rightTask.join();
            return leftSum + rightSum;
        }
    }
}
